package cn.csust.net2.manager.client.ux;
import java.util.List;
import java.util.Map;
import cn.csust.net2.manager.shared.util.TimeUtil;
import cn.csust.net2.manager.shared.vo.TreeNode;
import com.extjs.gxt.ui.client.data.BaseTreeLoader;
import com.extjs.gxt.ui.client.data.BeanModel;
import com.extjs.gxt.ui.client.data.RpcProxy;
import com.extjs.gxt.ui.client.data.TreeBeanModelReader;
import com.extjs.gxt.ui.client.event.BaseEvent;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.TreeStore;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.button.ButtonGroup;
import com.extjs.gxt.ui.client.widget.form.CheckBox;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
import com.extjs.gxt.ui.client.widget.treepanel.TreePanel;
import com.extjs.gxt.ui.client.widget.treepanel.TreePanel.CheckCascade;
import com.google.gwt.user.client.rpc.AsyncCallback;
/**
 * 
 * @author 韩忠金
 *
 */
public abstract class ExpandTree extends ContentPanel {
	/**
	 * 参数TRREENode 的名称
	 */
	public static final String TREE_NODE = "treeNode";
	/**
	 * 年级参数的名称
	 */
	public static final String GRADE_ITEMS = "gradeItems";
	/**
	 * 是否加入老师在TREE的参数名称
	 */
	public static final String TEACHER_ADD = "teacher_add";
	/**
	 * 参数:是否启动CHECK为TREE
	 */
	public static final String CHECKABLE = "checkAble";
	
	//TREE的视图
	public TreePanel<BeanModel> tree;
	//远程代理
	public RpcProxy<List<TreeNode>> treeProxy ;
	//解析器
	public TreeBeanModelReader reader;
	//客户端的数据缓存器
	public TreeStore<BeanModel> store;
	//数据加载器
	public BaseTreeLoader<BeanModel> loader;
	//加载树初始化的时候的条件
	public Map<String,Object> configs;
	//Tool
	public ToolBar toolBar ;
	//CHECKable
	public boolean checkAble;
	/**
	 * 加载条件初始化
	 * @param configs
	 */
	public ExpandTree(Class<? extends TreeNode> lastLeaf ,Map<String,Object> configs){
		this.lastLeaf = lastLeaf;
		this.configs = configs;
		Boolean checkConfig = (Boolean) configs.get(ExpandTree.CHECKABLE);
		if(checkConfig!=null){
			this.checkAble = checkConfig;
			configs.remove(ExpandTree.CHECKABLE);
		}
		this.setHeaderVisible(false);
		initTool();
		init();
	}
	/**
	 * 加载条件初始化
	 * @param configs
	 */
	public ExpandTree(Class<? extends TreeNode> lastLeaf,boolean isAutoLoad ,Map<String,Object> configs){
		this.isAutoLoad = isAutoLoad;
		this.lastLeaf = lastLeaf;
		this.configs = configs;
		Boolean checkConfig = (Boolean) configs.get(ExpandTree.CHECKABLE);
		if(checkConfig!=null){
			this.checkAble = checkConfig;
			configs.remove(ExpandTree.CHECKABLE);
		}
		this.setHeaderVisible(false);
		initTool();
		init();
	}
	/**
	 * 根据条件生成新的TREE（内存消耗）
	 * @param configs
	 */
	public void load(Class<? extends TreeNode> lastLeaf ,Map<String,Object> configs){
		
		addListeners();
		this.configs.putAll(configs);
		this.remove(tree);
		init();
		addListeners();
	}
	private Class<? extends TreeNode> lastLeaf;
	private void init(){
		//在布局信息发生变化时候可以重新刷新显示
		this.setLayoutOnChange(true);
		initRPC();
		initReader();
		initLoader();
		initStore();
		initTree();
		setLayout(new FitLayout());
		add(tree);
		
	}
	/**
	 * 初始化工具栏
	 */
	private void initTool(){
		toolBar = new ToolBar();
		final ButtonGroup group = new ButtonGroup(2);
	    final int grade = TimeUtil.getNowYear();
	    for(int i=0;i<4;i++){
	    	CheckBox check = new CheckBox();  
	    	check.setId(String.valueOf(grade-i));
	    	check.setBoxLabel(String.valueOf(grade-i));   
	    	group.add(check);
	    }
	    Button button = new Button("查看");
	    button.addSelectionListener(new SelectionListener<ButtonEvent>() {
		
			@Override
			public void componentSelected(ButtonEvent ce) {
				String [] items = new String[4];
				for(int i=0;i<4;i++){
					CheckBox cb = (CheckBox) group.getItemByItemId(String.valueOf(grade-i));
					if(cb.getValue()){
						items[i] = cb.getItemId();
					}
				}
				ExpandTree.this.load(items);
				
			}
		});
	   
	    group.setBorders(false);
	    toolBar.add(group);
	    toolBar.add(button);
	    if(this.checkAble){
		    Button check = new Button("选择");
		    check.addSelectionListener(new SelectionListener<ButtonEvent>() {
				
				@Override
				public void componentSelected(ButtonEvent ce) {
					
					 for (BeanModel item : tree.getCheckedSelection()) {
				         	TreeNode node = item.getBean();
				         	System.out.println("名称:"+node.getNodeName()+",ID:"+node.getNodeId()+",class:"+node.getSelf());
				      }
				}
			});
		    toolBar.add(check);
	    } 
	    this.setTopComponent(toolBar);
	}
	/**
	 * 初始化远程代理
	 */
	private void initRPC(){
		treeProxy = new RpcProxy<List<TreeNode>>() {

			@Override
			protected void load(Object loadConfig,	AsyncCallback<List<TreeNode>> callback) {
				TreeNode tn = null;
				if(loadConfig instanceof BeanModel&&loadConfig!=null){
					tn = ((BeanModel)loadConfig).getBean();
					
				}else{

					tn = (TreeNode) loadConfig;
				}
				ExpandTree.this.load(tn,configs, callback);
				
			}

		};
	}
	private void initReader(){
		 reader = new TreeBeanModelReader();
		
		/**
		 * 
		 * *********************************************************************
		 * ********************* 因为ModelBean是不可以直接被实力化的，所以当返回类型为LIST类型时候，
		 * BeanModelreader会用工厂去实例化每个bean，在其中如果这个属性不设置将会自动的
		 * 将所有的LIST中的BEAN都转化为第一个PO的类型，在这里因为返回的LIST中包含了2中对象一个是专业另外一个是老师，所以
		 * 需要设置该属性，这样每个bean都将得到自己的工厂 *******************
		 * 效率不高，考虑复写解析工厂的算法（GXT）**********************************
		 */
		reader.setFactoryForEachBean(true); 
	}
	private void initStore(){
		store = new TreeStore<BeanModel>(loader);
	}
	private void initLoader(){
		loader = new BaseTreeLoader<BeanModel>(treeProxy,reader) {
			@Override
			public boolean hasChildren(BeanModel parent) {
		//		System.out.println(parent.getBean().getClass().toString()+"1");
			//	System.out.println(lastLeaf.toString()+"2");
	//			return !(parent.getBean() instanceof TreeLeaf);
				
				return !(parent.getBean().getClass().toString().equals(lastLeaf.toString()));
			}
		};
	}
	private boolean isAutoLoad;
	private void initTree(){
		tree = new TreePanel<BeanModel>(store);
		tree.setStateful(true);
		tree.setAutoLoad(isAutoLoad);
		tree.setDisplayProperty("nodeName");
		 if(this.checkAble){
			tree.setCheckable(true);
			tree.setCheckStyle(CheckCascade.CHILDREN);  
		 }
	}
	//实例化的时候需要匿名补写这个函数，将RPC进行绑定
	protected abstract void load(Object loadConfig,Map<String,Object> configs,	AsyncCallback<List<TreeNode>> callback);
	protected abstract void load(String [] items);
	protected List<Listener<? extends BaseEvent>> listeners;
	//树的监听器
	protected void addListeners(){
		if(listeners==null)
			listeners = tree.getListeners(Events.OnDoubleClick);
		else{
			for(Listener<? extends BaseEvent> l:listeners)
				tree.addListener(Events.OnDoubleClick, l);
		}
	}
	public Class<? extends TreeNode> getLastLeaf() {
		return lastLeaf;
	}
	public void setLastLeaf(Class<? extends TreeNode> lastLeaf) {
		this.lastLeaf = lastLeaf;
	}
	public TreePanel<BeanModel> getTree() {
		return tree;
	}
	public void setTree(TreePanel<BeanModel> tree) {
		this.tree = tree;
	}
	
	
}
